<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="..\..\node_modules\vue\dist\vue.js"></script>
    <script src="..\..\node_modules\vuex\dist\vuex.js"></script>
</head>
<body>
<div id="app">
    {{a.c}}
    {{b.cc}}
    {{c}}
    <button v-on:click="addA_map">addA_map</button>
    <button v-on:click="addA_action">addA_action</button>
    <br>
    root
    {{this.$store.state.c}} {{this.$store.getters.getC}}
    <button v-on:click="addR">add</button>
    <br>
    a
    {{this.$store.state.a.c}} {{this.$store.getters['a/getC']}}
    <button v-on:click="addA">add</button>
    <br>
    b
    {{this.$store.state.b.cc}} {{this.$store.getters['getCC']}}
    <button v-on:click="addB">add</button>
    <br>
</div>
<script type="application/javascript">
    Vue.use(Vuex);

    // namespaced每个级别都需要配置。
    // 如果不配置，则集成父级命名空间，上下级别不能有重名内容。
    const moduleA = {
        namespaced: true,
        //通过方法返回state数据，避免交叉干扰，类似Component.data。
        state: () => (
            {
                c:0
            }
        ),
        mutations: {
            increment(state){
                state.c++;
            },
        },
        getters:{
            getC(state , getters , rootState , rootGetters){
                return state.c;
            }
        },
        actions:{
            incrementAsyn(context){
                console.log('incrementAsyn');
                // 通过第三个参数控制调用root state
                context.commit('increment' , {} , {root:true});
            },
            action4Root: {
                root: true,
                handler (namespacedContext, payload) {
                    console.log("action4Root called.");
                }
            }
        }
    };

    const moduleB = {
        state: {
            cc:10
        },
        mutations: {
            incrementCC(state){
                state.cc++;
            },
        },
        getters:{
            getCC(state , getters , rootState , rootGetters){
                return state.cc;
            }
        },
        actions:{
            incrementCCAsyn(context){
                console.log('incrementCCAsyn');
            }
        }
    };

    const store = new Vuex.Store({
        namespaced: true,
        state: {
            c:100
        },
        mutations: {
            increment(state){
                state.c++;
            },
        },
        getters:{
            getC(state , getters , rootState , rootGetters){
                return state.c;
            }
        },
        actions:{
            //context里面什么都有。
            incrementAsyn(context){
                console.log('incrementAsyn');
                context.dispatch("action4Root");
            }
        },
        modules: {
            a: moduleA
        }
    });

    // 注册模块 'b'
    // preserveState只覆盖方法，不覆盖数据。
    store.registerModule('b', moduleB, { preserveState: true });
    // 其他注册操作。
    // store.unregisterModule(moduleName);
    // store.hasModule(moduleName);

    //范围a的4个map，利用解构简化语法。
    const { mapState, mapActions } = Vuex.createNamespacedHelpers('a');

    var app = new Vue({
        el:"#app",
        data:{store:store},
        store,
        methods: Object.assign(
                {
                    addA:function(){
                        this.store.commit("a/increment");
                        this.store.dispatch("a/incrementAsyn");
                    },
                    addB:function(){
                        this.store.commit("incrementCC");
                        this.store.dispatch("incrementCCAsyn");
                    },
                    addR:function(){
                        this.store.commit("increment");
                        this.store.dispatch("incrementAsyn");
                    },
                    addA_map:function(){
                        this["a/increment"]();
                    },
                    addA_action:function(){
                        this["incrementAsyn"]();
                    }
                },
                Vuex.mapMutations(["a/increment" , "incrementCC" ,"increment" ]),
                mapActions(["incrementAsyn"])
        ),
        computed: Vuex.mapState([
                "a", "b","c"
        ])
    });

</script>
</body>
</html>